/**
 * Copyright (c) 2011 Alessandro Camillo'.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

#include "VWSGSensor.h"
#include "printf.h"

generic module VWSGSensorP(uint8_t accepted_type) {

	provides {
//		interface							SplitControl;
		interface							Read<uint16_t>;
//		interface							VWSGSensorDebug;
		interface							Msp430UartConfigure;
	}
	uses {
		// interface HplMsp430GeneralIO as		GIO;

	  interface GeneralIO  as GIO;
		interface UartStream as	SensorStream;
		interface	Resource;
		
		
		interface Timer<TMilli> as StartupTimer;
		interface Timer<TMilli> as Timeout;
		
		interface	Leds;


//		interface Timer<TMilli> as			Loop;

	}

}
implementation {

	msp430_uart_union_config_t msp430_uart_telos_config = { 
		{ ubr: UBR_1MHZ_9600, 
			umctl: UMCTL_1MHZ_9600, 
			ssel: 0x02, 
			pena: 0, 
			pev: 0, 
			spb: 0, 
			clen: 1, 
			listen: 0, 
			mm: 0, 
			ckpl: 0, 
			urxse: 0, 
			urxeie: 1, 
			urxwie: 0, 
			utxe : 1, 
			urxe : 1} 
	};
	// msp430_uart_union_config_t msp430_uart_telos_config = { {ubr: UBR_1MHZ_115200, umctl: UMCTL_1MHZ_115200, ssel: 0x02, pena: 0, pev: 0, spb: 0, clen: 1, listen: 0, mm: 0, ckpl: 0, urxse: 0, urxeie: 1, urxwie: 0, utxe : 1, urxe : 1} };
	// msp430_uart_union_config_t msp430_uart_telos_config = { {ubr: UBR_1MHZ_2400, umctl: UBR_1MHZ_2400, ssel: 0x02, pena: 0, pev: 0, spb: 0, clen: 1, listen: 0, mm: 0, ckpl: 0, urxse: 0, urxeie: 1, urxwie: 0, utxe : 1, urxe : 1} };

  uint8_t board_cmd[VWSG_BOARD_CMD_BUFFER_SIZE];

	uint8_t m_buffer[ VWSG_BUFFER_SIZE ];
	
	uint8_t m_status = VWSG_BOARD_OFF ;
	uint16_t m_byte_received = 0 ;
	
	uint16_t m_value;
	bool m_busy = FALSE;

	task void read();
	task void readDone();

  bool setReset = TRUE;


//	command error_t SplitControl.start() {
//		atomic {
//			m_status	= VWSG_BOARD_OFF;
//			m_byte_received = 0;
//			m_busy = FALSE;
//		}
//
////		call GIO.makeOutput();
//
//	 //	call Loop.startPeriodic( 1000 );
//
//		signal SplitControl.startDone( SUCCESS );
//		return SUCCESS;
//	}

//	command error_t SplitControl.stop() {
//		signal SplitControl.stopDone( SUCCESS );
//		return SUCCESS;
//	}

	task void request() {
		call Resource.request();
	}

	command error_t Read.read() {
//		printf("%s 1\n", __FUNCTION__);
//		printfflush();

		call GIO.makeOutput();

		if ( m_busy == TRUE ){
			printf("%s, EBUSY\n", __FUNCTION__);
			printfflush();
			return EBUSY;
		}

		if ( call Resource.immediateRequest() != SUCCESS ) {
			post request();
			printf("%s, request()\n", __FUNCTION__);
			printfflush();

			return SUCCESS;
		}

		m_busy = TRUE;
		
		post read();
	//	printf("[%s, read()2]\n", __FUNCTION__);
	//	printfflush();

		return SUCCESS;
	}

	task void read() {
		uint8_t i;
//		printf("starting.. %s status:%u \n", __FUNCTION__, m_status);
//		printfflush();

#ifdef VWSG_USE_TIMEOUT
		call Timeout.startOneShot( VWSG_TIMEOUT + VWSG_STARTUP_TIME );
#endif


		for ( i = 0; i < VWSG_BUFFER_SIZE; i ++ )
			m_buffer[ i ] = 0;
	
		m_byte_received = 0;
	
		if ( m_status == VWSG_BOARD_OFF) {		
			/*
			** Power the board ON
			*/
			call Leds.set( 7 );
			call GIO.set();
		}
		
		m_status = VWSG_BOARD_ON;
		
		/*
		** Give enough time to the board to startup
		*/
		call StartupTimer.startOneShot( VWSG_STARTUP_TIME );

//		printf("leaving.. %s\n", __FUNCTION__);
//		printfflush();
	}

	task void readDone() {
		uint16_t snd_value_;
		
		atomic {
			snd_value_ = m_value;
		}
		
		m_busy = FALSE;
		m_status	= VWSG_BOARD_OFF;
		m_byte_received = 0;

		call Resource.release();
		signal Read.readDone( SUCCESS, snd_value_ );
	}

	task void loadValue() {
		uint8_t		i;
		
#ifdef VWSG_USE_TIMEOUT
		call Timeout.stop();
#endif
//		call Leds.led2Toggle();
		

		
		m_value = 0;
		
		for( i=0; i < m_byte_received; i++ )
		{
			m_value = m_value * 10 + (m_buffer[i] - '0');
		}


		m_buffer[ m_byte_received ] = 0;
		printf("%s, b:<%s> l:%u value:%u\n", __FUNCTION__, (char *)m_buffer, m_byte_received, m_value);
		printfflush();

		
		/*
		** Check if the board was actrive and sent us
		** a meaningful answer (that is different from "0000")
		*/
		if (m_value == 0)
		{
			post read();
			return;
		}

		
		/*
		** Power the board off
		*/
		call GIO.clr();
		call Leds.set( 0 );
		m_status = VWSG_BOARD_OFF;

		post readDone();
	}


	/*
	** the board should be ready
	*/
	event void StartupTimer.fired() {
//		printf("%s status:%u \n", __FUNCTION__, m_status);	
//		m_buffer[m_byte_received] = 0;
//		printf("<%s> \n", m_buffer);
//		printfflush();

		/*
		** initialize/reset the board
		*/

/*****
		board_cmd[0] = VWSG_RESET_BOARD;
		board_cmd[1] = VWSG_END_CMD_TOKEN;

		board_cmd[0] = VWSG_RESET_BOARD;
		board_cmd[1] = VWSG_END_CMD_TOKEN;

		call SensorStream.send( board_cmd, sizeof(VWSG_RESET_BOARD_SIZE) + 1);
****/

		board_cmd[0] = VWSG_GET_SAMPLING;
		board_cmd[1] = VWSG_CHANNEL;
		board_cmd[2] = VWSG_END_CMD_TOKEN;
		printf("Sending read command\n") ;
		printfflush() ;
		call SensorStream.send( board_cmd, sizeof(VWSG_GET_SAMPLING_SIZE) + 1);

	}


	async event void SensorStream.receivedByte( uint8_t data ) {
//		printf("%s\n", __FUNCTION__);
//		printfflush();

		if ( m_status == VWSG_BOARD_SAMPLING )
		{
			m_buffer[ m_byte_received ++ ] = data;
			
			if ( m_byte_received == VWSG_SAMPLE_SIZE )
			{
				m_status = VWSG_BOARD_DATA_READY;
				post loadValue();
			}
		}
//		m_buffer[ m_byte_received ] = 0;
//		printf("%s, s:%s l:%u\n", __FUNCTION__, (char *)m_buffer, m_byte_received);
//		printfflush();
	}

	async event void SensorStream.sendDone( uint8_t* buf, uint16_t len, error_t error ) 
	{
	
//			printf("%s Gx SENT , status: %u\n",__FUNCTION__,  m_status);

		/*
		** Let's check the status. If the status is BOARD ON (initialized)
		** then we can ask for sampling the sensor
		*/
		if ( m_status == VWSG_BOARD_ON )
			m_status = VWSG_BOARD_SAMPLING;
		printf("command sent\n") ;
		printfflush() ;
			
		
//		if ( m_status == VWSG_BOARD_ON )
//		{
//			m_status = VWSG_BOARD_SAMPLING;
			
//			board_cmd[0] = VWSG_GET_SAMPLING;
//			board_cmd[1] = VWSG_CHANNEL;
//			board_cmd[2] = VWSG_END_CMD_TOKEN;
//			call SensorStream.send( board_cmd, sizeof(VWSG_GET_SAMPLING_SIZE) + 1);
//		}
//		else
//		if ( m_status == VWSG_BOARD_SAMPLING )
//		{
//			/*
//			** The board should have a sample read ready
//			*/
//		}
			
	}

	async event void SensorStream.receiveDone( uint8_t* buf, uint16_t len, error_t error ) {}

	async command msp430_uart_union_config_t* Msp430UartConfigure.getConfig() {
		return & msp430_uart_telos_config;
	}

	event void Resource.granted() {
		m_busy = TRUE;
// #ifdef VWSG_USE_TIMEOUT
// 		call Timeout.startOneShot( VWSG_TIMEOUT + VWSG_STARTUP_TIME );
// #endif
		post read();
	}

	event void Timeout.fired() {
		printf("%s \n", __FUNCTION__);
		printfflush();

		call GIO.clr();
		call Leds.set( 0 );
		atomic {
			m_status	= VWSG_BOARD_OFF;
			m_byte_received = 0;
			m_busy = FALSE;
		}
		
		call Resource.release();
		signal Read.readDone( FAIL, 0xFFFF );
	}

}
